import { gameMain, GameMain } from "../GameMain";
import { MapPlayer } from "./MapPlayer";
import { MsgId, MsgToc, MsgVo } from "../../../config/Msg";
import { TowerAOI, TowerEventId } from "./TowerAOI";
import { Vec2 } from "../../../common/vec2/Vec2";
import { Xlsx } from "../../../config/Xlsx";

/**
 * 地图基类
 */
export class BaseMap {

    id: number = 1;
    players: MapPlayer[] = [];
    playerDic: { [pid: number]: MapPlayer } = {}
    aoi: TowerAOI;
    tps = 10;

    constructor(id: number) {
        this.id = id;
        let cfg = this.cfg;
        this.aoi = new TowerAOI(cfg.size[0], cfg.size[1], cfg.towerSize[0], cfg.towerSize[1]);
        this.aoi.on(TowerEventId.EntityAdd, (watchers, entities) => {
            for (let watcher of watchers) {
                if (watcher instanceof MapPlayer) {
                    let players = entities.filter(e => e != watcher);
                    players.length && gameMain.app.backendSvr.send(watcher.frontSid, watcher.pid, MsgId.addPlayer, { players });
                }
            }
        });
        this.aoi.on(TowerEventId.EntityDel, (watchers, entities) => {
            for (let watcher of watchers) {
                if (watcher instanceof MapPlayer) {
                    let players = entities.filter(e => e != watcher) as MapPlayer[];
                    players.length && gameMain.app.backendSvr.send(watcher.frontSid, watcher.pid, MsgId.delPlayer, { pids: players.map(p => p.pid) });
                }
            }
        });
        this.aoi.on(TowerEventId.EntityUpdate, (watchers, entities) => {
            for (let watcher of watchers) {
                if (watcher instanceof MapPlayer) {
                    let players = entities.filter(e => e != watcher);
                    players.length && gameMain.app.backendSvr.send(watcher.frontSid, watcher.pid, MsgId.syncPlayer, { players: entities.filter(e => e != watcher) });
                }
            }
        });
    }

    start() {
        let last = Date.now();
        setInterval(() => {
            let now = Date.now();
            this.update((now - last) * 0.001);
            last = now;
        }, 1000 / this.tps);
    }

    update(dt: number) {
        this.players.forEach(player => {
            if (player.sync) {
                player.ang = Vec2.ins.angTo(player, player.sync);
                player.x = player.sync.x;
                player.y = player.sync.y;
                player.sync = null;
                this.aoi.updateEntity(player);
                this.aoi.updateWatcher(player);
            }
        });
    }

    addPlayer(player: MapPlayer) {
        if (this.playerDic[player.pid]) return;
        player.map = this;
        let [x, y] = this.cfg.spawnPos[0];
        let [wc, wh] = this.cfg.watchSize;
        player.x = x;
        player.y = y;
        player.watchWidth = wc;
        player.watchHeight = wh;
        this.players.push(player);
        this.playerDic[player.pid] = player;
        this.aoi.addEntity(player);
        this.aoi.addWatcher(player);
        gameMain.app.backendSvr.send(player.frontSid, player.pid, MsgId.addPlayer, { players: [player] });
    }

    delPlayer(pid: number) {
        let player = this.playerDic[pid];
        if (!player) return;
        player.map = null;
        this.players.splice(this.players.indexOf(player), 1);
        delete this.playerDic[pid];
        this.aoi.delEntity(player);
        this.aoi.delWatcher(player);
        gameMain.app.backendSvr.send(player.frontSid, player.pid, MsgId.delPlayer, { pids: [player.pid] });
    }

    get cfg() { return Xlsx.map.get(this.id); }

}